//this is a module that stitching and caching data
//Last modified by yjq at 2021/5/20

module Input(
    input wire clk,
    input wire rst_n,
    input wire new,
    input wire in_valid,
    input wire input_W_read,
    input wire[7:0] data_in,

    output wire out_valid,//replace empty.
    output reg[31:0] W
);

reg [31:0] W1;
reg [31:0] W2;
reg [31:0] W3;
reg [31:0] W4;
reg [31:0] W5;
reg [31:0] W6;
reg [31:0] W7;
reg [31:0] W8;
reg [31:0] W9;
reg [31:0] W10;
reg [31:0] W11;
reg [31:0] W12;

//status
reg [2:0] bitflag_mask;//Each bit means that 8bit of tmp data is filled.
reg [13:0]bitflag_fifo;//Each bit means that 32bit of fifo unit is filled.

reg [23:0]tmp_in;
assign empty = bitflag_fifo==14'b0;//fifo is empty.
assign in_ = in_valid && bitflag_mask==3'b111; //A data_32bit come in at this posedge.
assign out_= input_W_read && ~empty; //A data_32bit come out at this posedge.
assign out_valid = out_;

//bitflag_mask
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        bitflag_mask<=3'b0;
    end else begin
        if(new)
            bitflag_mask<=3'b0;
        else if(in_valid)begin 
            bitflag_mask<=(bitflag_mask==3'b0)?3'b1:
            (bitflag_mask==3'b1)?3'b11:
            (bitflag_mask==3'b11)?3'b111:
            (bitflag_mask==3'b111)?3'b0:3'b0;
        end
    end
end

//bitflag_fifo
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        bitflag_fifo<=14'b0;
    end else begin
        if(new)
            bitflag_fifo<=14'b0;
        else if(in_ && !out_)
            bitflag_fifo<={{bitflag_fifo[12:0]},1'b1};
        else if(out_ && !in_)
            bitflag_fifo<={1'b0,{bitflag_fifo[13:1]}};
    end //DAta format of bitflag_fifo is 0s appended by 1s.
end

//tmp_in
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        tmp_in<=24'b0;
    end else begin
        if(in_valid)begin 
            if(bitflag_mask==3'b0)
                tmp_in[7:0]<=data_in;
            else if(bitflag_mask==3'b1)
                tmp_in[15:8]<=data_in;
            else if(bitflag_mask==3'b11)
                tmp_in[23:16]<=data_in;
        end
    end
end


/*
generate
       genvar i;
       for(i=0;i<SIZE-1;i=i+1)
       begin:Ws
            always@(posedge clk or negedge rst_n)begin
                if(!rst_n)begin
                    Ws[i]<=32'b0;
                end else begin
                    if(in_ && (i==0)?empty:((&bitflag_fifo[i-1:0])&&~(bitflag_fifo[SIZE-1,i])))
                        Ws[i]<={data_in,tmp_in};
                    else if(out_)
                        Ws[i]<=Ws[i+1];
                end
            end
       end
endgenerate 
*/

//fifo units are as follows.
//W
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        W<=32'b0;
    end else begin
        if(in_ && bitflag_fifo==14'b0)
            W<={data_in,tmp_in};
        else if(out_)
            W<=W1;
    end
end

//W1
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        W1<=32'b0;
    end else begin
        if(in_ && bitflag_fifo==14'b1)
            W1<={data_in,tmp_in};
        else if(out_)
            W1<=W2;
    end
end

//W2
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        W2<=32'b0;
    end else begin
        if(in_ && bitflag_fifo==14'b11)
            W2<={data_in,tmp_in};
        else if(out_)
            W2<=W3;
    end
end

//W3
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        W3<=32'b0;
    end else begin
        if(in_ && bitflag_fifo==14'b111)
            W3<={data_in,tmp_in};
        else if(out_)
            W3<=W4;
    end
end

//W4
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        W4<=32'b0;
    end else begin
        if(in_ && bitflag_fifo==14'hf)
            W4<={data_in,tmp_in};
        else if(out_)
            W4<=W5;
    end
end

//W5
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        W5<=32'b0;
    end else begin
        if(in_ && bitflag_fifo==14'h1f)
            W5<={data_in,tmp_in};
        else if(out_)
            W5<=W6;
    end
end

//W6
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        W6<=32'b0;
    end else begin
        if(in_ && bitflag_fifo==14'h3f)
            W6<={data_in,tmp_in};
        else if(out_)
            W6<=W7;
    end
end
//W7
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        W7<=32'b0;
    end else begin
        if(in_ && bitflag_fifo==14'h7f)
            W7<={data_in,tmp_in};
        else if(out_)
            W7<=W8;
    end
end

//W8
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        W8<=32'b0;
    end else begin
        if(in_ && bitflag_fifo==14'hff)
            W8<={data_in,tmp_in};
        else if(out_)
            W8<=W8;
    end
end

//W9
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        W9<=32'b0;
    end else begin
        if(in_ && bitflag_fifo==14'h1ff)
            W9<={data_in,tmp_in};
        else if(out_)
            W9<=W10;
    end
end

//W10
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        W10<=32'b0;
    end else begin
        if(in_ && bitflag_fifo==14'h3ff)
            W10<={data_in,tmp_in};
        else if(out_)
            W10<=W11;
    end
end
//W11
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        W11<=32'b0;
    end else begin
        if(in_ && bitflag_fifo==14'h7ff)
            W11<={data_in,tmp_in};
        else if(out_)
            W11<=W12;
    end
end

//W12
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        W12<=32'b0;
    end else begin
        if(in_ && bitflag_fifo==14'hfff)
            W12<={data_in,tmp_in};
    end
end


endmodule